package com.fbli.config;

import com.fbli.service.UserServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.rememberme.JdbcTokenRepositoryImpl;
import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository;

import javax.sql.DataSource;

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    MyAccessDeniedHandler myAccessDeniedHandler;
    @Autowired
    UserServiceImpl userService;
    @Autowired
    private DataSource dataSource;
    @Autowired
    private PersistentTokenRepository tokenRepository;
    @Autowired
    private MyAuthenticationEntryPoint myAuthenticationEntryPoint;
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        //表单登录
        http.formLogin()
                //自定义登录页面
                .loginPage("/login.html")
                //自定义登录逻辑
                .loginProcessingUrl("/login")
                //登录成功后跳转页面,必须是post请求
                .successForwardUrl("/toMian")
                //自定义登录成功后跳转逻辑
                //.successHandler(new MyAuthenticationSuccessHandler("http://www.baidu.com"))
                //登录成功后跳转页面,必须是post请求
                //.failureForwardUrl("/toError")
                //自定义登录成功后跳转逻辑
                .failureHandler(new MyAuthenticationFailureHandler("/error.html"))
                //自定义登录用户名参数
                .usernameParameter("username")
                //自定义登录密码参数
                .passwordParameter("password");

        //授权
        http.authorizeRequests()
                //放行页面
                //.antMatchers("/login.html").permitAll()
                .antMatchers("/login.html").access("permitAll()")
                .antMatchers("/error.html").permitAll()
                .antMatchers("/image/**").permitAll()//放行**匹配0个或多个目录 *匹配0个或多个字符 ？匹配一个字符
                .regexMatchers(HttpMethod.POST,".+[.]png").permitAll()//正则表达式匹配
                .antMatchers("/main1.html").hasAuthority("admin")//根据权限匹配
                //.antMatchers("/main1.html").hasAnyAuthority("admin","Admin")//根据权限匹配
                .antMatchers("/main1.html").hasRole("abc")//根据角色匹配，不能以ROLE_下划线开头，严格区分大小写
                .antMatchers("/main1.html").hasIpAddress("127.0.0.1")//根据ip匹配
                //自定义认证
                .anyRequest().access("@myServiceImpl.hasPremission(request,authentication)");
                //所有请求都必须认证
                //.anyRequest().authenticated();
        //异常处理
        http.exceptionHandling()
                //.authenticationEntryPoint(myAuthenticationEntryPoint)//没有认证信息401
                .accessDeniedHandler(myAccessDeniedHandler);//未授权403
        //记住我
        http.rememberMe()
                //自定义参数
                //.rememberMeParameter()
                //自定义登录逻辑
                .userDetailsService(userService)
                //自定义功能实现逻辑
                //.rememberMeServices()
                //指定存储位置
                .tokenRepository(tokenRepository);
        //退出登录
        http.logout()
                .logoutUrl("/logout")
                .logoutSuccessUrl("/login.html");
        //关闭csrf防护
        http.csrf().disable();

    }
    @Bean
    public PasswordEncoder pw(){return new BCryptPasswordEncoder();}
    @Bean
    public PersistentTokenRepository tokenRepository(){
        JdbcTokenRepositoryImpl tokenRepository=new JdbcTokenRepositoryImpl();
        //设置数据源
        tokenRepository.setDataSource(dataSource);
        //启动时是否创建表,第一次要，后面注释掉
        //tokenRepository.setCreateTableOnStartup(true);
        return tokenRepository;
    }
}
